<?php
/** 
 * Copyright (c) 2012, Jiehun.com.cn Inc. All Rights Reserved
 * @author Ronnie(dengxiaolong@jiehun.com.cn)
 * @date 2012-2-11
 * @version 1.0 
 * @brief 
 *  城市选项
 **/
final class Address
{
	private static $level1s;
	private static $level2s;
	private static $level3s;
	private static $level4s;
	
	private static $inited = false;
	
	private static $specialCities = array(110000 => array('北京', '110900'), 120000 => array('天津', '120300'), 310000 => array('上海','310900'), 500000 => array('重庆', '500900'));
	const ELSEAREA_CODE = '95'; //其他地区的代码
	
	public function __construct()
	{
		if (!self::$inited) {
			self::$level1s = include dirname(__FILE__).'/cities/level1.php';
			self::$level2s = include dirname(__FILE__).'/cities/level2.php';
			self::$level3s = include dirname(__FILE__).'/cities/level3.php';
			self::$level4s = include dirname(__FILE__).'/cities/level4.php';
			self::$inited = true;
		}
	}
	
	/**
	 * 通过id找到地区
	 * Enter description here ...
	 * @param int $id
	 * @return array | null
	 * <code>array(
	 * 	level: int 级别
	 *  id：int id
	 *  name： string 名称
	 *  sname: string 大于两个字以上的地名，去掉行政级别。如：上海市对应的短名称为上海
	 *  address: string 地址名称
	 *  parent：array 父级地区
	 * )</code>
	 */
	public function get($id)
	{
		$level = $this->getIdLevel($id);
		$firstId = substr($id, 0, 2).'0000';
		switch($level) {
			case 1:
				if (isset(self::$level1s[$id])) {
					if (isset(self::$specialCities[$id])) {
						$name = self::$specialCities[$id][0];
					} else {
						$name = self::$level1s[$id];
					}
					return array(
						'level' => 1,
						'id' => $id,
						'name' => $name,
						'sname' => $this->getShortName($name),
						'address' => $name,
					);
				}
				break;
			case 2:
				if (isset(self::$level2s[$id])) {
					$name = self::$level2s[$id];
					$ret = array(
						'level' => 2,
						'id' => $id,
						'name' => $name,
						'sname' => $this->getShortName($name),
						'parent' => $this->get($firstId),
					);
					$address = '';
					if (!isset(self::$specialCities[$firstId]) && $ret['parent']) {
						$address = $ret['parent']['address'];
					}
					$address .= $name;
					$ret['address'] = $address;
					return $ret;
				}
				break;
			case 3:
				if (isset(self::$level3s[$id])) {
					$name = self::$level3s[$id];
					
					if (isset(self::$specialCities[$firstId])) {
						$parentId = self::$specialCities[$firstId][1];
					} else {
						$parentId = substr($id, 0, 4).'00';
					}
					
					$ret = array(
						'level' => 3,
						'id' => $id,
						'name' => self::$level3s[$id],
						'sname' => $this->getShortName($name),
						'parent' => $this->get($parentId),
					);
					// 如果是其他区域，则地址只返回二级区域名称
					$address = substr($id, -2) == self::ELSEAREA_CODE ? '' : $name;
					if ($ret['parent']) {
						$address = $ret['parent']['address'].$address;
					}
					$ret['address'] = $address;
					return $ret;
				}
				break;
			case 4:
				if (isset(self::$level4s[$id])) {
					$name = self::$level4s[$id];
					
					$parentId = substr($id, 0, 6);
					
					$ret = array(
						'level' => 4,
						'id' => $id,
						'name' => self::$level4s[$id],
						'parent' => $this->get($parentId),
					);
					$address = $ret['parent']['address'];
					$ret['address'] = $address;
					return $ret;
				}
				break;
		}
		
		return null;
	}
	
	/**
	 * 通过id列表获取一组城市
	 * @param unknown_type $ids
	 */
	public function getByIds($ids)
	{
		$ret = array();
		foreach($ids as $id) {
			$ret[$id] = $this->get($id);
		}
		return $ret;
	}
	
	/**
	 * 通过地址寻找对应的id
	 * @param string $addr
	 */
	public function getIdByAddress($addr)
	{
		$id1 = 0;
		$name1 = '';
		foreach(self::$level1s as $id => $name) {
			if (mb_strpos($addr, $name) === 0) {
				$id1 = $id;
				$name1 = $name;
				break;
			}
		}
		if ($id1 == 0) return 0;
		
		
		$id2 = 0;
		$name2 = '';
		if (mb_substr($name1, -1) == '市') { // 如果是直辖市
			foreach(self::$level2s as $id => $name) {
				if ($name1 == $name) {
					$id2= $id;
					$name2 = $name;
					break;
				}
			}
		} else {
			$addr = mb_substr($addr, mb_strlen($name1));
			if (!$addr) return $id1;
			
			$level2s = $this->getLevel2s($id1);
			foreach($level2s as $id => $name) {
				if (mb_strpos($addr, $name) === 0) {
					$id2 = $id;
					$name2 = $name;
					break;
				}
			}
		}
		
		if ($id2 == 0) return 0;
		$addr = mb_substr($addr, mb_strlen($name2));
		if (!$addr) return $id2;
		
		$level3s = $this->getLevel3s($id2);
		foreach($level3s as $id => $name) {
			if (mb_strpos($addr, $name) === 0) {
				return $id;
			}
		}
		return 0;
	}
	
	/**
	 * 获取城市的短名称
	 * @param string $name
	 * @return 
	 */
	private function getShortName($name)
	{
		if (mb_strlen($name) <= 2) {
			return $name;
		}
		return preg_replace('/(省|县|市|区|.族自治[区县]|特别行政区)$/u', '', $name);
	}
	
	/**
	 * 获取id的级别
	 * @param int $id
	 */
	private function getIdLevel($id) {
		if(strlen($id)==9){
			return 4;
		} else if (substr($id, 2, 4) == '0000') {
			return 1;
		} else if (substr($id, 4, 2) == '00') {
			return 2;
		} else {
			return 3;
		}
	}
	
	/**
	 * 获取指定id的下一级所有地区
	 * 
	 * @param $id 如果不指定，则返回1级地区
	 * @return array()
	 */
	public function getChilds($id = 0)
	{
		if (!$id) {
			return self::$level1s;
		}
		$level = $this->getIdLevel($id);
		
		switch($level) {
			case 1:
				return $this->getLevel2s($id);
			case 2:
				return $this->getLevel3s($id);
			case 3:
				return $this->getLevel4s($id);
			default:
				return array();
		}
	}
	/**
	 * 获取指定城市下的所有商区
	 * @param $id 
	 * @param $hot true:热门   默认false
	 * @return array()
	 */
	public function getBusiness($id = 0 , $hot=false)
	{
		if (!$id) {
			return array();
		}
		$ret = array();
		$find = false;
		$firstId = substr($id, 0, 2).'0000';
		if (isset(self::$specialCities[$firstId])) {
			$cmpId = substr($id, 0, 2);
		}else{
			$cmpId = substr($id, 0, 4);
		}
		foreach(self::$level4s as $id=>$name) {
			$pos = strpos($id, $cmpId);
			if (!$find && $pos === 0) {
				$find = true;
			} else if ($find && $pos === false) {
				break;
			}
			if ($find) {
				if(!$hot){
					$ret[$id] = $name;
				}else{
					$hotid = substr($id, 6, 1);
					if($hotid == 8){
						$ret[$id] = $name;
					}
				} 
			}
		}
		return $ret;
	}

	/**
	 * 获取二级地区
	 * 
	 * @param int $level1Id
	 */
	private function getLevel2s($level1Id)
	{
		if (!isset(self::$level1s[$level1Id])) {
			throw new Exception('city.level1NotExists provinceId='.$level1Id);
		}
		
		return $this->getCitiesByPrefix(substr($level1Id, 0, 2), 2);
	}
	
	/**
	 * 获取三级地区
	 * 
	 * @param int $level2Id
	 * @throws Exception
	 */
	private function getLevel3s($level2Id)
	{
		if (!isset(self::$level2s[$level2Id])) {
			throw new Exception('city.level2NotExists provinceId='.$level2Id);
		}
		$firstId = substr($level2Id, 0, 2).'0000';
		if (isset(self::$specialCities[$firstId])) {
			return $this->getCitiesByPrefix(substr($level2Id, 0, 2), 3);
		}
		
		return $this->getCitiesByPrefix(substr($level2Id, 0, 4), 3);
	}
	
	/**
	 * 获取四级地区
	 * 
	 * @param int $level3Id
	 * @throws Exception
	 */
	private function getLevel4s($level3Id)
	{
		if (!isset(self::$level3s[$level3Id])) {
			return array();
		}
		return $this->getCitiesByPrefix($level3Id, 4);
	}
	
	/**
	 * 通过前缀查找城市
	 * 
	 * @param int $cmpId
	 * @param int $level
	 */
	private function getCitiesByPrefix($cmpId, $level) {
		$ret = array();
		$find = false;
		
		$propName = 'level'.$level.'s';
		
		foreach(self::$$propName as $id=>$name) {
			$pos = strpos($id, $cmpId);
			if (!$find && $pos === 0) {
				$find = true;
			} else if ($find && $pos === false) {
				break;
			}

			if ($find) {
				$ret[$id] = $name;
			}
		}
		return $ret;
	}
	
	/**
	 * 生成城市
	 */
	private function generateCities()
	{
		$path = dirname(__FILE__).'/cities.txt';
		$to = dirname(__FILE__).'./cities.php';
		
		$file_handle = fopen($path, "r");
		$cities = array();
		while (!feof($file_handle)) {
		   $line = trim(fgets($file_handle));
		   
		   list($id, $name) = explode(' ', $line);
		   if ( substr($id, 2, 4) == '0000' ) {
		   		$cities[0][$id] = $name;
		   } else if (substr($id, 4, 2) == '00') {
		   		$cities[1][$id] = $name;
		   } else {
		   		$cities[2][$id] = $name;
		   }
		}
		fclose($file_handle);
		
		file_put_contents(dirname(__FILE__).'/cities/level1.php', "<?php\nreturn ". var_export($cities[0], true).';');
		file_put_contents(dirname(__FILE__).'/cities/level2.php', "<?php\nreturn ". var_export($cities[1], true).';');
		file_put_contents(dirname(__FILE__).'/cities/level3.php', "<?php\nreturn ". var_export($cities[2], true).';');
	}
}
